package com.songlanyun.modules.offlinegoods.service.impl;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.BeanUtil;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;
import com.songlanyun.modules.offlinegoods.dao.OfflineGoodsDao;
import com.songlanyun.modules.offlinegoods.entity.OfflineGoods;
import com.songlanyun.modules.offlinegoods.exception.OfflineGoodsExceptionEnum;
import com.songlanyun.modules.offlinegoods.model.dto.OfflineGoodsDTO;
import com.songlanyun.modules.offlinegoods.service.OfflineGoodsService;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

/**
 * 线下商品
 *
 * @author lijiahe
 * @date 2023-02-11
 */
@Service("offlineGoodsService")
public class OfflineGoodsServiceImpl extends ServiceImpl<OfflineGoodsDao, OfflineGoods> implements OfflineGoodsService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OfflineGoods create(OfflineGoods entity) {
        baseMapper.insert(entity);
        return entity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OfflineGoods modify(OfflineGoods entity) {
        baseMapper.updateById(entity);
        return entity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Long id) {
        baseMapper.deleteById(id);
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Integer isUp = MapUtil.getInt(params, "isUp");
        Integer type = MapUtil.getInt(params, "type");
        Long typeId = MapUtil.getLong(params, "typeId");
        Long userId = MapUtil.getLong(params, "userId");
        Long shopId = MapUtil.getLong(params, "shopId");
        String name = MapUtil.getStr(params, "name");
        IPage<OfflineGoods> page = this.page(new Query<OfflineGoods>().getPage(params),
            new LambdaQueryWrapper<OfflineGoods>().eq(ObjectUtil.isNotNull(isUp), OfflineGoods::getIsUp, isUp)
                .eq(ObjectUtil.isNotNull(type), OfflineGoods::getType, type)
                .eq(ObjectUtil.isNotNull(typeId), OfflineGoods::getTypeId, typeId)
                .eq(ObjectUtil.isNotNull(userId), OfflineGoods::getCreateBy, userId)
                .eq(ObjectUtil.isNotNull(shopId), OfflineGoods::getShopId, shopId)
                .like(ObjectUtil.isNotNull(name), OfflineGoods::getName, name)
                .orderByDesc(OfflineGoods::getCreateTime));
        return new PageUtils(page);
    }

    @Override
    public OfflineGoods loadOfflineGoodsById(Long id, Boolean tw) {
        OfflineGoods offlineGoods = this.getById(id);
        if (offlineGoods == null && tw) {
            throw new RRException(OfflineGoodsExceptionEnum.OFFLINE_GOODS_NOT_EXISTS);
        }
        return offlineGoods;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDto(OfflineGoodsDTO dto) {
        if (ObjectUtil.isNull(dto)) {
            return;
        }
        this.validateNameExists(dto.getName(), dto.getShopId());

        OfflineGoods entity = new OfflineGoods();
        this.setOfflineGoods(dto, entity);
        baseMapper.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDto(Long shopId, OfflineGoodsDTO dto) {
        if (ObjectUtil.isNull(dto)) {
            return;
        }
        OfflineGoods entity = this.loadOfflineGoodsById(dto.getId(), true);
        this.validateOfflineGoodsSafe(shopId, entity);
        if (!StrUtil.equals(dto.getName(), entity.getName())) {
            this.validateNameExists(dto.getName(), shopId);
        }
        this.setOfflineGoods(dto, entity);
        baseMapper.updateById(entity);
    }

    private void setOfflineGoods(OfflineGoodsDTO dto, OfflineGoods entity) {
        BeanUtil.copyPropertiesIgnoreNull(dto, entity);
        Integer isRelease = dto.getIsRelease();
        if(NumberUtil.equals(isRelease, BigDecimal.ONE.intValue())) {
            entity.setIsUp(BigDecimal.ONE.intValue());
        }
        List<String> detailsImages = dto.getDetailsImages();
        if (CollectionUtil.isNotEmpty(detailsImages)) {
            entity.setDetailsImages(detailsImages);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteWithValidById(Long id, Long shopId, Boolean isValid) {
        OfflineGoods entity = this.loadOfflineGoodsById(id, true);
        this.validateOfflineGoodsSafe(shopId, entity);
        if (isValid) {
            Integer isUp = entity.getIsUp();
            if (NumberUtil.equals(isUp, BigDecimal.ONE.intValue())) {
                throw new RRException(OfflineGoodsExceptionEnum.OFFLINE_GOODS_CANNOT_CANNOT_BE_DELETED);
            }
        }
        baseMapper.deleteById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void upOrOffShelf(Long id, Long shopId) {
        OfflineGoods entity = this.loadOfflineGoodsById(id, true);
        this.validateOfflineGoodsSafe(shopId, entity);
        if (NumberUtil.equals(entity.getIsUp(), BigDecimal.ONE.intValue())) {
            entity.setIsUp(BigDecimal.ZERO.intValue());
        } else {
            entity.setIsUp(BigDecimal.ONE.intValue());
        }
        baseMapper.updateById(entity);
    }

    /**
     * 验证下线商品名称不能重复
     *
     * @param name
     */
    private void validateNameExists(String name, Long shopId) {
        OfflineGoods target = baseMapper
            .selectOne(new LambdaQueryWrapper<OfflineGoods>()
                    .eq(OfflineGoods::getName, name)
                    .eq(OfflineGoods::getShopId, shopId)
                    .last("limit 1"));
        if (target != null) {
            throw new RRException(OfflineGoodsExceptionEnum.OFFLINE_GOODS_REPEAT);
        }
    }

    /**
     *  只能操作自己的线下商品
     */
    private void validateOfflineGoodsSafe(Long shopId, OfflineGoods offlineGoods) {
        if(!ObjectUtil.equal(offlineGoods.getShopId(), shopId)) {
            throw new RRException(OfflineGoodsExceptionEnum.OFFLINE_GOODS_SAFE);
        }
    }

}
